
#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>

#include "lcd.h"
#include "spi.h"
#include "timer.h"

#define DISP_W 132
#define DISP_H 32
#define NUM_PAGES	(DISP_H/8)

#define LCD_A0		PA5
#define LCD_RESET	PC6
#define LCD_CS		PC7

#define clr_A0()	(PORTA &= ~(1<<LCD_A0))
#define set_A0()	(PORTA |= (1<<LCD_A0))
#define clr_cs()	(PORTC &= ~(1<<LCD_CS))
#define set_cs()	(PORTC |= (1<<LCD_CS))
#define clr_reset()	(PORTC &= ~(1<<LCD_RESET))
#define set_reset()	(PORTC |= (1<<LCD_RESET))

uint8_t lcd_xpos;
uint8_t lcd_ypos;

void __send_byte (uint8_t data)
{
	clr_cs();
	spi_putc(data);
	set_cs();
}

void send_cmd(uint8_t cmd)
{
	clr_A0();
	__send_byte(cmd);
}

void send_data(uint8_t data)
{
	set_A0();
	//wait_ms(2);	
	__send_byte(data);
}

void lcd_cls (void)
{
	uint16_t i,j;
	
	for (i=0; i<NUM_PAGES; i++)
	{
		send_cmd(0xB0+i); // set Page address
		send_cmd(0x10); // set Column address MSB
		//send_cmd(0x04); // set Column address LSB
		send_cmd(0x00); // set Column address LSB

		// alle Zellen mit 0x00 beschreiben
		for (j=0; j<DISP_W; j++)
			send_data(0x00);
	}
	lcd_xpos = 0;
	lcd_ypos = 0;
}

void lcd_reset()
{
	set_cs();
	clr_reset();
	wait_ms(10);
	set_reset();
	//clr_cs();
}

void lcd_init (void)
{
	DDRC |= (1<<LCD_RESET) | (1<<LCD_CS);
	DDRA |= (1<<LCD_A0);
	PORTC |= (1<<LCD_RESET) | (1<<LCD_CS);

	lcd_xpos = 0;
	lcd_ypos = 0;
	
	//DDRB = 0xFF;
	//SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL)|(1<<SPR1); // vom LCD
	//SPCR0 = (1<<SPE0)|(1<<MSTR0) | (0<<SPR01)|(1<<SPR00); // vom MCP2515

	lcd_reset();
	send_cmd(0x40); // Display start line 0
	send_cmd(0xA0); // ADC reverse - A0 = normal - A1 = reverse
	send_cmd(0xC8); // C0 = normal - C8 = reverse
	send_cmd(0xA6); // Display normal
	send_cmd(0xA2); // set bias 1/9
	send_cmd(0x2F); // Booster/Regulator and Follower on
	send_cmd(0xF8); // set internal Booster to 3x/4x
	send_cmd(0x00); // -------- " " ----------
	send_cmd(0x23); // 
	send_cmd(0x81); //
	send_cmd(0x1F); //
	send_cmd(0xAC); // no Indicator, Display on
	send_cmd(0x00); // -------- " " ----------
	send_cmd(0xAF); // -------- " " ----------
	send_cmd(0xA4); // Display all points on
	lcd_cls();
}

void set_adress (uint16_t adress, uint8_t data)
{
	uint8_t page;
	uint8_t column;
	
	page = (adress / DISP_W);
	
	send_cmd(0xB0 + page); // set Page address	
	column = (adress % DISP_W);
	send_cmd(0x10 + (column >> 4));
	send_cmd(column & 0x0F);
	send_data(data);
}
